using QntPlatform.Strategy.S2;
using System;
using System.Linq;

namespace QntPlatform.Strategy.CmdCtrl
{

    /// <summary>
    /// 给定止盈点，分步止盈，1/3止盈，1/3止盈提升止损，1/3追踪止盈
    /// </summary>
    public class StepProfit : CmdHandlePart
    {
       readonly decimal amSum;
        decimal nowAmount;
        StrategyBase2 strategyBase2;
        decimal profitSlideDownRate = 0.85m;
       public decimal StopProfitForSlideRate { get; set; }=0.01m;
        public StepProfit(IStrategy  parent,TvCmdHandler.AutoSellOrder autoSellOrder) : base(parent)
        {
            AutoSellOrder= autoSellOrder;
            amSum = autoSellOrder.Amount;
            nowAmount = amSum;
            strategyBase2 = parent as StrategyBase2;
        }
        public override void Init()
        {
            Exchange.TickerChangeEvent += Exchange_TickerChangeEvent;
        }
        private void Exchange_TickerChangeEvent(object sender, Ticker e)
        {
            if (strategyBase2 != null && strategyBase2.IsEnd)
            {
                OnExit();
            }
            TickerChangeListening(e);
        }

        TvCmdHandler.AutoSellOrder AutoSellOrder;
       
        public override void OnExit(Exception ex = null)
        {
            Exchange.TickerChangeEvent -= Exchange_TickerChangeEvent;
            //Parent.OnExit();
        }

        public decimal greedyRoundSplit(decimal source,decimal form) {
          var fp=  Exchange.getAmount(form);
           return fp == 0 ? source : fp;
        }
        TrailingProfit lastTP;
      public  void TickerChangeListening(Ticker tck)
        {
            var item = AutoSellOrder;
            //检查止损
            if (ISysFun.calcUnitProfit(tck.Buy, item.StopLossPrice, AutoSellOrder.Direction == SideDirection.CloseBuy) <= 0)
            {
                log.Debug("止损交易:", new { item, tck });
               // execTrade(item.Direction, item.Amount,item);
                Exchange.CreateOrder(nowAmount, item.Direction,info:new Db.LogInfo (){ ParentActId=item.SourceOrderId+"",Info2="止损,市价:"+tck.Buy });
                OnExit();
                return;
            }
            //检查止盈，跟踪止盈
            if (item.ProfitStep==2)
            {
                if (lastTP==null)
                {
                    log.Error("lastTP为null");
                    return;
                    //OnExit(new ArgumentException("lastTP为null"));
                }
                if (lastTP.Check(tck.Last))
                {
                    //execTrade(item.Direction, lastTP.Amount, new { lastTP,tck.Last});
                    Exchange.CreateOrder(lastTP.Amount, item.Direction, info: new Db.LogInfo() { ParentActId = item.SourceOrderId + "", Info2 = "止盈,市价:"+tck.Last });
                    OnExit();
                }
                return;
            }
            /*
            1.止损（7根k最小值）,止盈（给定值）
            2.当达到第一止盈时：卖出1/3，止损不变
            3.当达到第二止盈时：卖出1/3，止损改为买入价
            4.最后1/3跟踪 
            */
            if (item.ProfitStep > 1 ) 
                return;
          
            var upf= ISysFun.calcUnitProfit(tck.Buy,item.ProfitPrices[item.ProfitStep],item.Direction==SideDirection.CloseBuy);
           
             if (upf<0)
                return;
            //var amSum = item.Amount;
            var amount = greedyRoundSplit(amSum, item.Amount / 3);
            var rea = amSum - amount;
            var amount1 = greedyRoundSplit(rea, rea / 2);
            var amount2 = amSum - amount - amount1;

            if (item.ProfitStep == 0)
            {

                //amount = greedyRoundSplit(item.Amount, item.Amount / 3);
                //var id = execTrade(item.Direction, amount, new { nowBuy = tck.Buy });
                var id = Exchange.CreateOrder(amount, item.Direction, info: new Db.LogInfo() { Info2 = "止盈1/3" });
                item.ProfitStep++;
                // var rea = item.Amount - amount;
                item.Amount = amount1; //Exchange.getAmount(item.Amount 2/ 3);
                nowAmount -= amount1;
                item.StopLossPrice = item.SourcePrice;
                item.ProcInfo.Add($"止盈0成交,原仓位:{item.Amount},成交id:{id},止损变更:{item.StopLossPrice}");
                log.Debug("s3止盈成交0：", $"{item.SourceOrderId},{item.Amount},{item.ProcInfo.Aggregate((p1, p2) => p1 + "," + p2)}");
                return;
            }
            else if (item.ProfitStep == 1)
            {
                //var amount = item.Amount / 2;
                IConvertible id = 0;
                if (amount1 > 0)
                  //  id = execTrade(item.Direction, amount1, new { nowBuy = tck.Buy });
               id= Exchange.CreateOrder(amount1, item.Direction, info: new Db.LogInfo() { ParentActId = item.SourceOrderId + "", Info2 = "止盈1/3,市价:" + tck.Buy }).Result;

                item.ProfitStep++;
                item.Amount = amount2;
                nowAmount -= amount2;
               
                item.ProcInfo.Add($"止盈1成交,原仓位:{item.Amount},成交id:{id}");
                log.Debug("s3止盈成交1,忽略最后1/3：", $"{item.SourceOrderId},{item.Amount},{item.ProcInfo.Aggregate((p1, p2) => p1 + "," + p2)}");
                lastTP = new TrailingProfit()
                {
                    InitPrice = tck.Buy,
                    IsLong = item.Direction == SideDirection.CloseBuy,
                    Amount = amount2,
                    profitSlideRate=StopProfitForSlideRate
                };
                return;
            } 
            else
            {
                throw new QntException("无法处理的步骤", item);
            }
        }
       
        /// <summary>
        /// 追踪止盈信息数据
        /// </summary>
    class TrailingProfit
    {
            /// <summary>
            /// 最高盈利率
            /// </summary>
            public decimal topProfitRate { get; private set; } 
            /// <summary>
            /// 初始价格
            /// </summary>
           public decimal InitPrice { get; set; }
            /// 止盈回撤率
            public decimal profitSlideRate { get; set; }= 0.001m;
            /// 止盈率
            //public decimal profitRate { get; set; }
            public  bool IsLong { get; set; }
            public decimal Amount { get; set; }
           public bool Check(decimal nowPrice) {
                var nowRate = ISysFun.CalcProfitRate(nowPrice, InitPrice,IsLong);
                if (nowRate > topProfitRate)
                {
                    topProfitRate = nowRate;
                    return false;
                }
                if ((topProfitRate - nowRate) >= topProfitRate * profitSlideRate)
                {
                    return true;
                }
                return false;
            }
        }
    }



}
